﻿using System;
using System.Collections.Generic;
using System.Data;
using System.Linq;
using SubSonic;

namespace Medianamik.Core.Sugar
{
    public static class DataUtil
    {
        private static string inclusiveOperator = "%";
        private static string nonInclusiveOperator = "_%";
        public static string GetSQLInclusivityOperator(bool pIsInclusive)
        {
            return pIsInclusive ? inclusiveOperator : nonInclusiveOperator;
        }

        private static char[] delimiterChars = { '.' };
        public static List<Guid> GetBottomToTopNodeIds(string pPath, bool pInclusive, int pDepth)
        {
            if (pPath == null)
            {
                return new List<Guid>();
            }
            List<Guid> nodeIds = pPath.Split(delimiterChars, StringSplitOptions.RemoveEmptyEntries).ToList().ConvertAll<Guid>(id => new Guid(id));

            nodeIds.Reverse();

            if (pDepth > 0)
            {
                int numberOfItemsToRemove = (nodeIds.Count - (pDepth + 1));
                if (numberOfItemsToRemove > 0)
                {
                    nodeIds.RemoveRange((pDepth + 1), numberOfItemsToRemove);
                }
            }

            if (!pInclusive)
                nodeIds.RemoveAt(0);

            return nodeIds;
        }

        public static bool HasColumn(this IDataRecord dr, string columnName)
        {
            for (int i = 0; i < dr.FieldCount; i++)
            {
                if (dr.GetName(i).Equals(columnName, StringComparison.InvariantCultureIgnoreCase))
                    return true;
            }
            return false;
        }

        public static List<string> GetSelectedIds(string value)
        {
            if (!string.IsNullOrEmpty(value))
            {
                return value.Split(new[] { ',' }, StringSplitOptions.RemoveEmptyEntries).ToList();
            }
            return Enumerable.Empty<string>().ToList();
        }

        public static IList<Guid> GetSelectedGuids(string value)
        {
            var ids = new HashSet<Guid>();

            GetSelectedIds(value).ForEach(v =>
            {
                Guid id;

                if (!String.IsNullOrEmpty(value) && StringHelper.IsGuid(v, out id))
                    ids.Add(id);
            });

            return ids.ToList();
        }

        public static List<HierarchicalDataItem> ToHierarchicalListWithArtificialRoot(this IEnumerable<NodeType> list)
        {
            List<HierarchicalDataItem> hierarchicalList = new List<HierarchicalDataItem>();
            hierarchicalList.Insert(0, new HierarchicalDataItem() { ID = Guid.Empty, ParentID = null, Name = "Racine" });
            hierarchicalList.AddRange(list.Select(i => new HierarchicalDataItem() { ID = i.ID, ParentID = i.ParentID ?? Guid.Empty, Name = i.Name }));
            return hierarchicalList;
        }

        public static IEnumerable<TSource> Page<TSource>(this IEnumerable<TSource> source,
        int page, int pageSize)
        {
            return source.Skip((page - 1) * pageSize).Take(pageSize);
        }

        public static IEnumerable<Where> GetWhereIn<T>(this string columnName, IList<T> list)
            where T : IMedianamikDTO
        {
            return columnName.GetWhereIn(list.Select(x => x.NodeId).ToList());
        }

        public static IEnumerable<Where> GetWhereIn(this string columnName, IList<Guid> list)
        {
            return columnName.GetWhereIn(list.Select(d => d.ToString()).ToList());
        }

        public static IEnumerable<Where> GetWhereIn(this string columnName, IList<string> list)
        {
            if (list.Count == 0)
                return Enumerable.Empty<Where>();

            var where = new Where { ColumnName = columnName };

            if (list.Count == 1)
            {
                where.ParameterValue = list.First();
            }
            else if (list.Count > 0)
            {
                where.Comparison = Comparison.In;
                where.ParameterValue = list;
            }

            return new[] { where };
        }

        public static void AddRange<TKey, TValue>(this IDictionary<TKey, TValue> dict,
            IEnumerable<KeyValuePair<TKey, TValue>> range)
        {
            foreach (var kvp in range)
            {
                dict.Add(kvp);
            }
        }

        public static string GetCSharpTypeName(NodeTypeProperty property)
        {
            switch (property.DataType.SQLDataTypeName.ToLower())
            {
                case "int":
                    return "int?";
                case "float":
                    return "double?";
                case "uniqueidentifier":
                    return "Guid?";
                case "datetime":
                    return "DateTime?";
                case "bit":
                    return "bool?";
                case "varchar":
                case "nvarchar":
                case "nvarchar(max)":
                    return "string";
                default:
                    throw new NotImplementedException();
            }
        }

        public static Type GetCSharpType(NodeTypeProperty property, bool nullable)
        {
            string typeName;

            switch (property.DataType.SQLDataTypeName.ToLower())
            {
                case "int":
                    typeName = nullable ? "System.Nullable`1[System.Int32]" : "System.Int32";
                    break;
                case "float":
                    typeName = nullable ? "System.Nullable`1[System.Double]" : "System.Double";
                    break;
                case "uniqueidentifier":
                    typeName = nullable ? "System.Nullable`1[System.Guid]" : "System.Guid";
                    break;
                case "datetime":
                    typeName = nullable ? "System.Nullable`1[System.DateTime]" : "System.DateTime";
                    break;
                case "bit":
                    typeName = nullable ? "System.Nullable`1[System.Boolean]" : "System.Boolean";
                    break;
                case "char":
                    typeName = "System.Char";
                    break;
                case "varchar":
                case "nvarchar":
                case "nvarchar(max)":
                    typeName = "System.String";
                    break;
                default:
                    throw new NotImplementedException();
            }

            return Type.GetType(typeName);
        }
    }
}